home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / pcmagazi / assemblr / 04 / undel.asm < prev    next >
Assembly Source File  |  1986-02-05  |  12KB  |  248 lines

  1.  
  2.         COMMENT*--------------------------------------------------------
  3.               This program will undelete files. To use, type UNDEL FILE.EXT or
  4.         UNDEL DRIVE:FILE.EXT where DRIVE is A or B. For ASCII files use UNDEL/A 
  5.         FILE.EXT or UNDEL/A DRIVE:FILE.EXT; this prints out what is in each
  6.         cluster before it adds it to the file and asks (Y/N) if it's correct. 
  7.         Only for use with DOS 2.0 and 2.10 double sided disks.
  8.         ---------------------------------------------------------------*
  9.         FCB_LOC EQU     5CH     ;Location of FCB for deleted file in the PSP
  10.         SWITCH_LOC EQU  81H     ;Location of text typed after 'UNDEL'
  11.         BIG_A   EQU     412FH   ;Test chars for /A
  12.         SMALL_A EQU     612FH   ;Test chars for /a
  13.         CR      EQU     13      ;ASCII carriage return
  14.         LF      EQU     10      ;ASCII line feed
  15. CODE_SEG        SEGMENT
  16.         ASSUME  CS:CODE_SEG,DS:CODE_SEG,ES:CODE_SEG
  17.         ORG     100H            ;To make this a .com file
  18. ENTRY:  JMP     FIRST           ;Skip over data area
  19.  
  20.         COPY_RIGHT      DB      '(C) 1984 S HOLZNER'
  21.         I_O_FLAG        DW ?    ;Selects read or write of cluster
  22.         START_CLUSTER   DW ?    ;Beginning cluster of deleted file
  23.         FILE_SIZE       DW ?    ;File size in clusters (1 cluster=2 sectors)
  24.         DISK_DRIVE      DB 0    ;Drive of deleted file
  25.         NOT_FOUND_MSG   DB 13,'File not found deleted$'        ;Messages
  26.         WRITTEN_OVER_MSG DB 13,'File already written over$'
  27.         IS_IT_MSG       DB 13,10,'Is part of your file here? (Y/N) $'
  28.  
  29.         DATA    DB 1024 DUP(0)  ;Space for disk directory and FAT
  30.         PROMPT_SECTOR  DB 512 DUP(0)    ;/A option uses for parts of file
  31.  
  32. FIRST:                          ;Start the process
  33. UNDEL   PROC    NEAR
  34.         MOV     AL,CS:FCB_LOC   ;Get the drive specified - 0 if none given
  35.         SUB     AL,1            ;Was it a 1 (A:) or 2 (B:)?
  36.         JNC     DRIVE_KNOWN     ;Yes, store drive number
  37.         MOV     AH,19H          ;No, get default drive from INT 21H
  38.         INT     21H
  39. DRIVE_KNOWN:
  40.         MOV     DISK_DRIVE,AL   ;Store drive
  41.         MOV     DX,3            ;Start to search dir, starts at sector 5
  42. LOOP:   ADD     DX,2            ;Add two to point at correct dir cluster
  43.         CMP     DX,11           ;Past end of directory?
  44.         JB      READ_DIR        ;If not, read dir into data area
  45.         MOV     AH,9            ;Past end of dir & no match, exit with error
  46.         LEA     DX,NOT_FOUND_MSG
  47.         INT     21H
  48.         JMP     OUT             ;Exit
  49. READ_DIR:
  50.         AND     I_O_FLAG,0      ;Select read
  51.         CALL    CLUSTER_I_O     ;Get two sectors into data area
  52.         LEA     DI,DATA         ;Prepare to search for deleted entry
  53.         MOV     AL,0E5H         ;DOS set first char of deleted entry to E5H
  54.         MOV     CX,400H         ;Counter=1024 to search this entire dir cluster
  55. SEARCH:                         ;Look-for-next-deleted-entry loop
  56. REPNE   SCASB
  57.         JCXZ    LOOP            ;If no match (Counter=0), get next dir cluster
  58.         MOV     SI,FCB_LOC+2    ;Possible match, point to 2nd char of file name
  59.         MOV     BX,11           ;Compare all chars in name
  60. CMPLOOP:DEC     BX              ;Decrement the name comparison loop counter
  61.         CMPS    [DI],[SI]       ;Compare dir entry and deleted file name
  62.         JZ      CMPLOOP         ;If match, check next char
  63.         CMP     BX,0            ;Compare done, all chars matched perfectly?
  64.         JNZ     SEARCH          ;No, keep checking through this dir cluster
  65.         MOV     AX,CS:FCB_LOC+1         ;Yes, get file's first letter 
  66.         MOV     [DI-12],AX      ;Move it into deleted entry (replace E5H)
  67.  
  68.         OR      I_O_FLAG,1      ;Select a write of 1 cluster
  69.         CALL    CLUSTER_I_O     ;Write directory with undeleted name to disk
  70.         MOV     AX,[DI+14]      ;Get starting cluster to use in FAT
  71.         MOV     START_CLUSTER,AX        ;Store it
  72.         MOV     AX,[DI+16]      ;Get low word of file size (in bytes)
  73.         TEST    AX,1023         ;Find # of clusters - is MOD(size,1024)=0?
  74.         JZ      EVEN_K          ;Yes, don't add 1 cluster before SHR
  75.         ADD     AX,1024         ;No, need another cluster
  76. EVEN_K: MOV     CL,10           ;Divide by 1024 (=cluster size)
  77.         SHR     AX,CL
  78.         MOV     DX,[DI+18]      ;High word of file size
  79.         MOV     CL,6            ;Multiply by 2^16=65536, divide by 2^10=1024
  80.         SHL     DX,CL
  81.         ADD     AX,DX           ;Add high word clusters to low word clusters
  82.         MOV     FILE_SIZE,AX    ;And store in FILE_SIZE
  83.         MOV     DX,1            ;Read in File Allocation Table (FAT)
  84.         AND     I_O_FLAG,0      ;Select a read of 1 cluster
  85.         CALL    CLUSTER_I_O
  86.         MOV     CX,FILE_SIZE    ;Counter to loop over # of clusters
  87.         MOV     AX,START_CLUSTER        ;Check if written over already
  88.         DEC     AX              ;Move back one cluster from beginning of file
  89.         CALL    GET_NEXT_ZERO   ;Is next empty space in FAT the START_CLUSTER?
  90.         CMP     DX,START_CLUSTER        
  91.         JE      FILL            ;Yes, OK to start filling FAT
  92.         MOV     AH,13H          ;No, file written over
  93.         MOV     DX,FCB_LOC      ;Delete restored dir entry; point to file name 
  94.         INT     21H             ;And delete it
  95.         MOV     AH,9            ;Exit with error
  96.         LEA     DX,WRITTEN_OVER_MSG
  97.         INT     21H
  98.         JMP     OUT             ;So long
  99. FILL:   MOV     AX,DX           ;Set old empty space in FAT to one just found
  100.         MOV     DX,0FFFH        ;Assume this is last entry (FFFH=End of file)
  101.         CMP     CX,1            ;Is it the last entry? (CX=cluster counter)
  102.         JZ      LAST            ;Yes, don't need to find next empty entry (zero)
  103.         CALL    GET_NEXT_ZERO   ;Call with AX=old zero, returns DX=new zero
  104. LAST:   CALL    PUT_FAT_ENTRY   ;Call with AX=old zero, DX=new zero, changes FAT
  105.         LOOP    FILL            ;Work on next cluster
  106.         MOV     DX,1            ;Prepare to write new FAT, 1st copy
  107.         OR      I_O_FLAG,1      ;Select to write 1 cluster
  108.         CALL    CLUSTER_I_O     ;Write the cluster
  109.         MOV     DX,3            ;Prepare to write new FAT, 2nd copy
  110.         CALL    CLUSTER_I_O
  111. OUT:    INT     20H             ;And leave
  112. UNDEL   ENDP                    
  113.  
  114. CLUSTER_I_O      PROC    NEAR    ;Reads specified cluster (dir, FAT etc.)
  115.         COMMENT* Put start sector in DX, loads Cluster into 'DATA' area*
  116.         PUSH    AX              ;Save the used registers
  117.         PUSH    BX              ;INT 25H destroys all reg.s
  118.         PUSH    CX
  119.         PUSH    DX
  120.         PUSH    DI
  121.         MOV     AL,DISK_DRIVE   ;Get disk drive
  122.         MOV     CX,2            ;Request 2 sectors (1 cluster) to be read
  123.         LEA     BX,DATA         ;Point to DATA area
  124.         TEST    I_O_FLAG,1
  125.         JNZ     WRITE
  126.         INT     25H             ;Read sector interrupt
  127.         JMP     POPOUT
  128. WRITE:  INT     26H
  129. POPOUT: POPF                    ;Pop the extra push of flags
  130.         POP     DI              ;Pop used (destroyed) registers
  131.         POP     DX
  132.         POP     CX
  133.         POP     BX
  134.         POP     AX
  135.         RET                     ;Return
  136. CLUSTER_I_O      ENDP
  137.  
  138. GET_NEXT_ZERO   PROC    NEAR    ;Unravel FAT and find next empty space in it
  139.         COMMENT* FAT entry number (cluster #) in AX, returns next zero in DX*
  140.         PUSH    AX              ;Push used reg.s
  141.         PUSH    BX
  142.         PUSH    CX
  143. CHECK_NEXT:                     ;Entry by entry loop
  144.         INC     AX              ;AX is entry pointer, start with next entry
  145.         MOV     BX,AX           ;Get 3/2*AX for actual offset into FAT 
  146.         SHL     BX,1            ; (Since each entry is 1.5 bytes)
  147.         ADD     BX,AX
  148.         SHR     BX,1            ;BX has FAT offset value for entry # in AX
  149.         MOV     DX,WORD PTR DATA[BX]        ;DX now has FAT entry's value
  150.         TEST    AX,1            ;Is the entry # even?
  151.         JZ      EVEN_ENTRY      ;Yes, use bottom 12 bits
  152.         MOV     CL,4            ;No, use top 12 bits
  153.         SHR     DX,CL
  154. EVEN_ENTRY:
  155.         AND     DX,0FFFH        ;Get bottom 12 bits (OK now for even or odd)
  156.         CMP     DX,0            ;Is the value for the given cluster # 0?
  157.         JNE     CHECK_NEXT      ;No, look for next cluster
  158.         MOV     DX,AX           ;Move entry value of zero into AX
  159.         CMP     AX,START_CLUSTER   ;If this is the 1st one, skip /A option
  160.         JE      POPS
  161.         MOV     BX,SWITCH_LOC   ;Was /A specified? Check data area in PSP
  162.         MOV     CX,[BX]         
  163.         CMP     CX,SMALL_A      ;Check for /a
  164.         JE      A_OPTION        ;Yes, do /A
  165.         CMP     CX,BIG_A        ;No, maybe a /A?
  166.         JNE     POPS            ;No, leave.
  167. A_OPTION:                       ;/A was specified
  168.         CALL    PRINT_OUT       ;Print out prompt sector
  169.         JCXZ    CHECK_NEXT      ;If CX set to 0, sector wasn't right
  170. POPS:   POP     CX              ;The pops before going
  171.         POP     BX
  172.         POP     AX
  173.         RET
  174. GET_NEXT_ZERO   ENDP
  175.  
  176. PRINT_OUT       PROC    NEAR    ;Print out a prompt sector
  177.         COMMENT* Returns CX=1 if found the right sector, 0 otherwise *
  178.         PUSH    DX              ;Push used reg
  179.         ADD     DX,DX           ;Get 2*DX for sector number
  180.         ADD     DX,8            ;Add 8 to skip boot, FATs and dir
  181.         MOV     AL,DISK_DRIVE   ;Get disk drive
  182.         MOV     CX,1            ;Ask for only 1 sector
  183.         LEA     BX,PROMPT_SECTOR        ;Load into PROMPT_SECTOR area
  184.         INT     25H             ;Read the sector
  185.         POPF                    ;Pop extra flags put on by INT 25H
  186.         MOV     AH,2            ;Prepare to print
  187.         MOV     DL,CR           ;Send a carriage return
  188.         INT     21H
  189.         MOV     DL,LF           ;Send a line feed
  190.         INT     21H
  191.         MOV     BX,0            ;Initialize char printout counter
  192. PRINT_LOOP:                     ;Like it says
  193.         MOV     DL,PROMPT_SECTOR[BX]    ;Get char from read-in cluster
  194.         INT     21H                     ;Print char
  195.         INC     BX                      ;Go on to next char
  196.         CMP     BX,160                  ;Done 160 Chars yet?
  197.         JBE     PRINT_LOOP              ;No; go back for more
  198.         MOV     AH,9                    ;Yes, print Prompt message
  199.         LEA     DX,IS_IT_MSG            
  200.         INT     21H
  201.         MOV     AH,1                    ;Get a char from keyboard
  202.         INT     21H
  203.         MOV     CX,1            ;Assume found right sector (always optimistic)
  204.         CMP     AL,'Y'          ;Was typed char a 'Y'?
  205.         JE      FOUND           ;Yes, found right sector exit with CX still=0
  206.         CMP     AL,'y'          ;No; was it a 'y'?
  207.         JE      FOUND           ;Yes, leave with CX still = 0
  208.         MOV     CX,0            ;Not found, exit with CX=1
  209. FOUND:  POP     DX              ;Pop destroyed DX reg
  210.         RET
  211. PRINT_OUT       ENDP
  212.  
  213. PUT_FAT_ENTRY   PROC    NEAR    ;Writes new FAT entry into FAT in DATA area
  214.         COMMENT* Pass FAT cluster number in AX and new entry in DX*
  215.         PUSH    AX              ;The requisite Pushes
  216.         PUSH    BX
  217.         PUSH    CX
  218.         PUSH    DX
  219.         MOV     BX,AX           ;Get offset into FAT, 3*AX/2
  220.         SHL     BX,1            ;Multiply by 2
  221.         ADD     BX,AX           ;Add AX to get 3*AX
  222.         SHR     BX,1            ;Divide by 2 -- BX has FAT offset value
  223.         TEST    AX,1            ;Do we have an even entry number?
  224.         JZ      P_EVEN_ENTRY    ;Yes, use bottom 12 bits
  225.         MOV     CL,4            ;No, use top 12 bits
  226.         SHL     DX,CL
  227. P_EVEN_ENTRY:
  228.         OR      WORD PTR DATA[BX],DX    ;Put Cluster # into FAT
  229.         POP     DX              ;Do the Pops
  230.         POP     CX
  231.         POP     BX
  232.         POP     AX
  233.         RET                     ;Return and you're done
  234. PUT_FAT_ENTRY   ENDP            
  235.  
  236. CODE_SEG        ENDS
  237.         END     ENTRY           ;This sets the starting address to ENTRY
  238.  
  239.  
  240.  
  241.  
  242.  
  243.  
  244.  
  245.  
  246.  
  247.  
  248.